
/**
 * Ext.ux.WindowSidePanel
 * @extends Ext.Toolbar
 * Creates and manages a sliding side panel for Ext.Windows
 */
Ext.ux.WindowSidePanel = function(config) {
	var config = config || {};
	Ext.apply(this, config);
};

Ext.ux.WindowSidePanel.prototype = {
	/**
	 * @property headerToolbarHidden
	 * @type Boolean
	 * Stores whether or not the window panel is currently hidden (collapsed).
	 * Set it to false if the window side panel should be displayed on render (defaults to true).
	 */
	windowSidePanelHidden	: true,

	/**
	 * Add the side panel to the the window and provide a getWindowSidePanel method
	 * @param {Ext.Window} The window to add a side panel to
	 */
	init					: function(win) {
		Ext.apply(win, {
			/**
			 * Somehow I like to pass the plugin config directly via the plugin config object,
			 * makes clear what plugin options can be set. Have to think about it though.
			 */
			windowSidePanelHidden	: this.windowSidePanelHidden,

			/**
			 * Somehow I like to pass the plugin config directly via the plugin config object,
			 * makes clear what plugin options can be set. Have to think about it though.
			 */
			windowSidePanel			: this.windowSidePanel,

			/**
			 * Adds to Windows's onRender method, creates window panel if everything required is in place
			 */
			onRender				: win.onRender.createSequence(function(ct,
					position) {
				if (this.windowSidePanel || this.filterPanelConfig) {
					this.windowSidePanel = this.windowSidePanel
							|| new Ext.ux.FilterPanel(this.filterPanelConfig);

					this.relayEvents(this.windowSidePanel, ['filters-updated']);

					// Create a side panel wrapper
					var wrapper = this.el.createChild({
								cls	: 'x-window-side-panel-wrapper'
							});

					// Create the toggler
					this.toggler = wrapper.insertFirst({
								cls	: 'x-window-side-panel-toggler'
							});

					// Render the panel into the window
					this.windowSidePanel.render(wrapper);

					// Create header and footer inside window panel
					this.windowSidePanel.el.insertFirst({
								cls	: 'x-window-side-panel-header'
							});
					this.windowSidePanel.el.createChild({
								cls	: 'x-window-side-panel-footer'
							});

					// create the shadows
					this.shadow = this.el.createChild({
								cls			: 'x-shadow',
								children	: [{
											cls			: 'xst',
											children	: [{
														cls	: 'xstl'
													}, {
														cls	: 'xstc'
													}, {
														cls	: 'xstr'
													}]
										}, {
											cls			: 'xsc',
											children	: [{
														cls	: 'xsml'
													}, {
														cls	: 'xsmc'
													}, {
														cls	: 'xsmr'
													}]
										}, {
											cls			: 'xsb',
											children	: [{
														cls	: 'xsbl'
													}, {
														cls	: 'xsbc'
													}, {
														cls	: 'xsbr'
													}]
										}]
							});

					this.on('render', this.anchorView, this);
					this.on('resize', this.resizeView, this);

					// In case we want to have the side panel open by default
					if (!this.windowSidePanelHidden)
						this.on('render', this.showWindowSidePanel, this);

					// Add click event to the toggler
					this.toggler.on('click', this.toggleWindowSidePanel, this);

					this.on({
						scope								: this,
						'before-collapse-header-toolbar'	: this.onHeaderToolbarCollapse,
						'before-expand-header-toolbar'		: this.onHeaderToolbarExpand
					}
					);
				};
			}
			),

			/**
			 * @return {Ext.Panel} The window panel, if one is available
			 */
			getWindowSidePanel		: function() {
				return this.windowSidePanel;
			},

			/**
			 * Anchors the window panel to the window on first render
			 */
			anchorView				: function() {
				var tempTask = new Ext.util.DelayedTask(function() {
							// Resize the view
							this.resizeView();
						}, this);
				tempTask.delay(1000);
			},

			/**
			 * Method which resizes the view according to the size of the window and also
			 * anchors it to the window
			 */
			resizeView				: function() {
				// Show the panel before resizing
				this.windowSidePanel.show();

				// get the bwrap, which is what we want to set the height attribute to
				var el = this.windowSidePanel.el
						.child('.x-window-side-panel-bwrap');
				var childEl = el.child('.x-window-side-panel-body');

				// Set the height of the side window panel and anchor the side panel to the window
				el.setHeight(this.el.getHeight() - 90);
				childEl.setHeight(el.getHeight() + 9);
				this.windowSidePanel.el.anchorTo(this.el, 'r-l', [0, 15]);

				this.currentWindowSidePanelHeight = el.getHeight();

				// anchor the toggler
				if (this.windowSidePanelHidden) {
					this.toggler.anchorTo(this.el, 'r-l');

					// hide the panel again
					this.windowSidePanel.hide();
				} else {
					this.toggler.anchorTo(this.windowSidePanel.el, 'r-l');
				};
			},

			/**
			 * Called when the header toolbar is collapsed
			 */
			onHeaderToolbarCollapse	: function() {
				var el = this.windowSidePanel.el
						.child('.x-window-side-panel-bwrap');
				var childEl = el.child('.x-window-side-panel-body');

				var top = parseFloat(this.windowSidePanel.el.dom.style.top
						.slice(0, this.windowSidePanel.el.dom.style.top.length
										- 2));
				var height = (this.windowSidePanelHidden)
						? this.currentWindowSidePanelHeight
						: el.getHeight();

				this.windowSidePanel.el.shift({
							duration	: 0.3,
							top			: top + 59
						});

				el.shift({
							duration	: 0.3,
							height		: height - 59
						});

				childEl.shift({
							duration	: 0.3,
							height		: height - 50
						});
			},

			/**
			 * Called when the header toolbar is expanded
			 */
			onHeaderToolbarExpand	: function() {
				var el = this.windowSidePanel.el
						.child('.x-window-side-panel-bwrap');
				var childEl = el.child('.x-window-side-panel-body');

				var top = parseFloat(this.windowSidePanel.el.dom.style.top
						.slice(0, this.windowSidePanel.el.dom.style.top.length
										- 2));
				var height = (this.windowSidePanelHidden)
						? this.currentWindowSidePanelHeight - 59
						: el.getHeight();

				this.windowSidePanel.el.shift({
							duration	: 0.3,
							top			: top - 59
						});

				el.shift({
							duration	: 0.3,
							height		: height + 59
						});

				childEl.shift({
							duration	: 0.3,
							height		: height + 68
						});
			},

			/**
			 * Collapses the window panel by sliding it to the right behind the window
			 * @param {Object} opts Options object passed to the slideOut call
			 */
			hideWindowSidePanel		: function(opts) {
				var opts = opts || {};
				Ext.applyIf(opts, {
							scope		: this,
							duration	: 0.3,
							callback	: function() {
								this.windowSidePanelHidden = true;
								this.windowSidePanel.hide();
							}
						});

				this.windowSidePanel.el.slideOut('r', opts);

				// shift the toggler
				this.toggler.shift({
							left		: -23,
							duration	: 0.3
						});

				this.toggler.removeClass('x-toggled');
			},

			/**
			 * Shows the window panel by sliding it to the left from behind the window
			 * @param {Object} opts Options object passed to the slideIn call
			 */
			showWindowSidePanel		: function(opts) {
				var opts = opts || {};
				Ext.applyIf(opts, {
							scope		: this,
							duration	: 0.3,
							callback	: function() {
								this.windowSidePanelHidden = false;
							}
						});

				this.windowSidePanel.show();

				this.windowSidePanel.el.slideIn('r', opts);

				// shift the toggler
				this.toggler.shift({
							left		: -163,
							duration	: 0.3
						});

				this.toggler.addClass('x-toggled');
			},

			/**
			 * Toggles the window panel between visible and hidden
			 */
			toggleWindowSidePanel	: function() {
				this.windowSidePanelHidden ? this.showWindowSidePanel() : this
						.hideWindowSidePanel();
			}
		}
		);
	}
};